package concurrent.lock;

import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.index.qual.SameLen;

import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.LockSupport;

/**
 * @program JavaBase
 *
 * @description: 先进先出独占锁
 * @author: zhanglu
 * @create: 2021-05-16 18:12:00
 */
@Slf4j
public class FifoMutexLock {

    private final static AtomicBoolean locked = new AtomicBoolean(false);
    private final static Queue<Thread> waiters = new ConcurrentLinkedQueue<>();

    public void lock(){
        boolean wasInterrupted = false;
        Thread current = Thread.currentThread();
        waiters.add(current);
        //如果当前线程不是队首或者当前锁已经被其他线程获取，则调用park()挂起自己
        while (waiters.peek() != current || !locked.compareAndSet(false, true)){
            LockSupport.park(this);
            //如果park()是因为被中断返回的，则忽略中断，并且中断标志位设置位true
            if(Thread.interrupted()){
                wasInterrupted = true;
            }
        }
        waiters.remove();
        locked.set(true);
        //判断中断标志位，如果true则中断该线程。其他线程中断了该线程，虽然我对中断信号不感兴趣，忽略它，
        //但是不代表其他线程对该标志位不感兴趣，所以这里设置线程中断
        if(wasInterrupted){
            current.interrupt();
        }
    }

    public void unlock(){
        locked.set(false);
        LockSupport.unpark(waiters.peek());
    }

    public static void main(String[] args) {
        log.info("" + locked.compareAndSet(false, true));
    }

}
